﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CoyoEden.Providers;
using System.ComponentModel;

namespace CoyoEden.Models
{
	public class Vote:BusinessBase<Vote,int>,IPublishable
	{
		#region .ctor
		static Vote() {
			Rate.Saved += new EventHandler<SavedEventArgs>(Rate_Saved);
			Rate.RatesBatchUpdated += new EventHandler<EventArgs>(Rate_RatesBatchUpdated);
		}
		public Vote() {
			Id = -1;
			_IsPublished = true;
			_Title = "Hi,I am a vote.";
			_Description = "";
			_Author = "";
			_VoteItems = new StateList<Rate>();
		}
		#endregion

		#region Member variables
		private bool _IsPublished;
		/// <summary>
		/// Gets or sets the IsPublished or the object.
		/// </summary>
		public bool IsPublished
		{
			get { return _IsPublished; }
			set
			{
				if (_IsPublished != value) MarkChanged("IsPublished");
				_IsPublished = value;
			}
		}
		private bool _IsMultiple;
		public bool IsMultiple {
			get { return _IsMultiple; }
			set {
				if (_IsMultiple != value) {
					MarkChanged("IsMultiple");
					_IsMultiple = value;
				}
			}
		}
		private readonly StateList<Rate> _VoteItems;
		public StateList<Rate> VoteItems
		{
			get { return _VoteItems; }
		}
		private static object _SyncRoot = new object();
		private static List<Vote> _Votes;
		/// <summary>
		/// A sorted collection of all posts in the blog.
		/// Sorted by date.
		/// </summary>
		public static List<Vote> Votes
		{
			get
			{
				if (_Votes == null)
				{
					lock (_SyncRoot)
					{
						if (_Votes == null)
						{
							_Votes = PortalService.FillVotes();
							_Votes.TrimExcess();
						}
					}
				}

				return _Votes;
			}
		}
		/// <summary>
		/// permanent link for the vote.Readonly
		/// </summary>
		public string PermaLink {
			get {
				return Utils.AbsoluteWebRoot + "Pages/Vote.aspx?id=" + Id.ToString();
			}
		}
		#endregion

		#region BusinessBase implementions
		public override bool IsChanged
		{
			get
			{
				if (base.IsChanged)
					return true;

				if (VoteItems.IsChanged)
					return true;

				return false;
			}
		}
		protected override void ValidationRules()
		{
			AddRule("Title", "标题非法[标题为空或者标题已经存在]", TitleRule());
		}

		protected override Vote DataSelect(int id)
		{
			return PortalService.SelectVote(id);
		}

		protected override void DataUpdate()
		{
			if (IsChanged) PortalService.UpdateVote(this);
		}

		protected override void DataInsert()
		{
			if (IsNew) PortalService.InsertVote(this);
		}

		protected override void DataDelete()
		{
			if (IsDeleted) PortalService.DeleteVote(this);
		}

		public new static Vote Load(int id)
		{
			Vote instance = new Vote();
			instance = instance.DataSelect(id);
			if (instance != null)
			{
				instance.Id = id;
				instance.MarkOld();
				return instance;
			}
			return null;

		}
		#endregion

		#region IPublishable Members
		private string _Title;
		/// <summary>
		/// Vote's title
		/// </summary>
		public string Title
		{
			get {
				return _Title;
			}
			set {
				if (_Title != value) {
					MarkChanged("Title");
					_Title = value;
				}
			}
		}
	
		/// <summary>
		///Same as  Vote's description
		/// </summary>
		public string Content
		{
			get { return _Description; }
		}

		public string RelativeLink
		{
			get {
				return Utils.RelativeWebRoot + "Vote/"+Id+".aspx";
			}
		}

		public Uri AbsoluteLink
		{
			get {
				var link = Utils.ConvertToAbsolute(RelativeLink);
				return link;
			}
		}
		private string _Description;
		/// <summary>
		/// Vote's description
		/// </summary>
		public string Description
		{
			get {
				return _Description;
			}
			set {
				if (_Description != value) {
					_Description = value;
					MarkChanged("Description");
				}
			}
		}
		private string _Author;
		/// <summary>
		/// vote 's author
		/// </summary>
		public string Author
		{
			get {
				return _Author;
			}
			set {
				if (null != _Author) {
					MarkChanged("Author");
					_Author = value;
				}
			}
		}

		/// <summary>
		/// Occurs when the post is being served to the output stream.
		/// </summary>
		public static event EventHandler<ServingEventArgs> Serving;
		/// <summary>
		/// Raises the event in a safe way
		/// </summary>
		public static void OnServing(Vote item, ServingEventArgs arg)
		{
			if (Serving != null)
			{
				Serving(item, arg);
			}
		}
		public void OnServing(ServingEventArgs eventArgs)
		{
			if (Serving != null)
			{
				Serving(this, eventArgs);
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <remarks>We don't need this</remarks>
		public StateList<Category> Categories
		{
			get { return null; }
		}

		public bool IsVisible
		{
			get {
				return _IsPublished;
			}
		}

		#endregion

		#region Methods
		/// <summary>
		/// Force reload of all votes
		/// </summary>
		public static void Reload()
		{
			_Votes = PortalService.FillVotes();
		}
		public static Vote GetVote(int id) {
			return Votes.Find(obj => obj.Id == id);
		}
		/// <summary>
		/// Add a new vote item
		/// </summary>
		/// <param name="item"></param>
		public void AddVoteItem(Rate item) {
			CancelEventArgs e = new CancelEventArgs();
			OnAddingVoteItem(item, e);
			if (!e.Cancel)
			{
				VoteItems.Add(item);
				DataUpdate();
				OnVoteItemAdded(item);
			}
		}
		/// <summary>
		/// Imports a vote item list to vote item collection and saves.  Does not
		/// notify user or run extension events.
		/// </summary>
		/// <param name="items"></param>
		public void ImportVoteItems(List<Rate> items) {
			VoteItems.AddRange(items);
			DataUpdate();
		}

		/// <summary>
		/// Removes a vote item from the collection and saves the Vote.
		/// </summary>
		/// <param name="item">The vote item to remove from the Vote.</param>
		public void RemoveVoteItem(Rate item)
		{
			CancelEventArgs e = new CancelEventArgs();
			OnRemovingVoteItem(item, e);
			if (!e.Cancel)
			{
				VoteItems.Remove(item);
				DataUpdate();
				OnVoteItemRemoved(item);
				item = null;
			}
		}
		/// <summary>
		/// Get current vote's raters number
		/// </summary>
		/// <returns></returns>
		public int GetVoteHits() {
			var retVal = 0;
			if (VoteItems != null) {
				VoteItems.ForEach(item => {
					retVal += item.Hits;
				});
			}
			return retVal;
		}
		/// <summary>
		/// Whether this Vote includes specified rater
		/// </summary>
		/// <param name="rater"></param>
		/// <returns></returns>
		public bool IncludeRater(string rater) {
			var retVal = false;
			if ((VoteItems != null) && (VoteItems.Count > 0)) {
				var tempObj= VoteItems.Find(item => {
					if ((item.RaterList != null) && item.RaterList.Contains(rater)) {
						return true;
					}
					return false;
				});
				if (tempObj != null) {
					retVal = true;
				}
			}
			return retVal;
		}
		#endregion

		#region business rules
		private bool TitleRule() {
			var isBroken = false;
			if (string.IsNullOrEmpty(Title))
			{
				isBroken = true;
			}
			else {
				var obj = Votes.Find(item =>item.Title.ToLowerInvariant()==Title.ToLowerInvariant()&&(item.Id!=this.Id));
				if (obj != null) {
					isBroken = true;
				}
			}
			return isBroken;
		}
		#endregion

		#region Events

		/// <summary>
		/// Occurs before a new vote item is added.
		/// </summary>
		public static event EventHandler<CancelEventArgs> AddingVoteItem;
		/// <summary>
		/// Raises the event in a safe way
		/// </summary>
		protected virtual void OnAddingVoteItem(Rate voteItem, CancelEventArgs e)
		{
			if (AddingVoteItem != null)
			{
				AddingVoteItem(voteItem, e);
			}
		}

		/// <summary>
		/// Occurs when a vote item is added.
		/// </summary>
		public static event EventHandler<EventArgs> VoteItemAdded;
		/// <summary>
		/// Raises the event in a safe way
		/// </summary>
		protected virtual void OnVoteItemAdded(Rate voteItem)
		{
			if (VoteItemAdded != null)
			{
				VoteItemAdded(voteItem, new EventArgs());
			}
		}

		/// <summary>
		/// Occurs before vote item is removed.
		/// </summary>
		public static event EventHandler<CancelEventArgs> RemovingVoteItem;
		/// <summary>
		/// Raises the event in a safe way
		/// </summary>
		protected virtual void OnRemovingVoteItem(Rate voteItem, CancelEventArgs e)
		{
			if (RemovingVoteItem != null)
			{
				RemovingVoteItem(voteItem, e);
			}
		}

		/// <summary>
		/// Occurs when a vote item has been removed.
		/// </summary>
		public static event EventHandler<EventArgs> VoteItemRemoved;
		/// <summary>
		/// Raises the event in a safe way
		/// </summary>
		protected virtual void OnVoteItemRemoved(Rate voteItem)
		{
			if (VoteItemRemoved != null)
			{
				VoteItemRemoved(voteItem, new EventArgs());
			}
		}
		#endregion

		#region Event handlers
		static void Rate_Saved(object sender, SavedEventArgs e)
		{
			if (e.Action == SaveAction.Delete || e.Action == SaveAction.Update)
			{
				Reload();
			}
		}
		static void Rate_RatesBatchUpdated(object sender, EventArgs e)
		{
			Reload();
		}
		#endregion
	}
}
